{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 基于用户的协同过滤算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入包\n",
    "import random\n",
    "import math\n",
    "import time\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一. 通用函数定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义装饰器，监控运行时间\n",
    "def timmer(func):\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start_time = time.time()\n",
    "        res = func(*args, **kwargs)\n",
    "        stop_time = time.time()\n",
    "        print('Func %s, run time: %s' % (func.__name__, stop_time - start_time))\n",
    "        return res\n",
    "    return wrapper"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 数据处理相关\n",
    "1. load data\n",
    "2. split data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Dataset():\n",
    "    \n",
    "    def __init__(self, fp):\n",
    "        # fp: data file path\n",
    "        self.data = self.loadData(fp)\n",
    "    \n",
    "    @timmer\n",
    "    def loadData(self, fp):\n",
    "        data = []\n",
    "        for l in open(fp):\n",
    "            data.append(tuple(map(int, l.strip().split('::')[:2])))\n",
    "        return data\n",
    "    \n",
    "    @timmer\n",
    "    def splitData(self, M, k, seed=1):\n",
    "        '''\n",
    "        :params: data, 加载的所有(user, item)数据条目\n",
    "        :params: M, 划分的数目，最后需要取M折的平均\n",
    "        :params: k, 本次是第几次划分，k~[0, M)\n",
    "        :params: seed, random的种子数，对于不同的k应设置成一样的\n",
    "        :return: train, test\n",
    "        '''\n",
    "        train, test = [], []\n",
    "        random.seed(seed)\n",
    "        for user, item in self.data:\n",
    "            # 这里与书中的不一致，本人认为取M-1较为合理，因randint是左右都覆盖的\n",
    "            if random.randint(0, M-1) == k:  \n",
    "                test.append((user, item))\n",
    "            else:\n",
    "                train.append((user, item))\n",
    "\n",
    "        # 处理成字典的形式，user->set(items)\n",
    "        def convert_dict(data):\n",
    "            data_dict = {}\n",
    "            for user, item in data:\n",
    "                if user not in data_dict:\n",
    "                    data_dict[user] = set()\n",
    "                data_dict[user].add(item)\n",
    "            data_dict = {k: list(data_dict[k]) for k in data_dict}\n",
    "            return data_dict\n",
    "\n",
    "        return convert_dict(train), convert_dict(test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 评价指标\n",
    "1. Precision\n",
    "2. Recall\n",
    "3. Coverage\n",
    "4. Popularity(Novelty)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Metric():\n",
    "    \n",
    "    def __init__(self, train, test, GetRecommendation):\n",
    "        '''\n",
    "        :params: train, 训练数据\n",
    "        :params: test, 测试数据\n",
    "        :params: GetRecommendation, 为某个用户获取推荐物品的接口函数\n",
    "        '''\n",
    "        self.train = train\n",
    "        self.test = test\n",
    "        self.GetRecommendation = GetRecommendation\n",
    "        self.recs = self.getRec()\n",
    "        \n",
    "    # 为test中的每个用户进行推荐\n",
    "    def getRec(self):\n",
    "        recs = {}\n",
    "        for user in self.test:\n",
    "            rank = self.GetRecommendation(user)\n",
    "            recs[user] = rank\n",
    "        return recs\n",
    "        \n",
    "    # 定义精确率指标计算方式\n",
    "    def precision(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(rank)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义召回率指标计算方式\n",
    "    def recall(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(test_items)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义覆盖率指标计算方式\n",
    "    def coverage(self):\n",
    "        all_item, recom_item = set(), set()\n",
    "        for user in self.test:\n",
    "            for item in self.train[user]:\n",
    "                all_item.add(item)\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                recom_item.add(item)\n",
    "        return round(len(recom_item) / len(all_item) * 100, 2)\n",
    "    \n",
    "    # 定义新颖度指标计算方式\n",
    "    def popularity(self):\n",
    "        # 计算物品的流行度\n",
    "        item_pop = {}\n",
    "        for user in self.train:\n",
    "            for item in self.train[user]:\n",
    "                if item not in item_pop:\n",
    "                    item_pop[item] = 0\n",
    "                item_pop[item] += 1\n",
    "\n",
    "        num, pop = 0, 0\n",
    "        for user in self.test:\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                # 取对数，防止因长尾问题带来的被流行物品所主导\n",
    "                pop += math.log(1 + item_pop[item])\n",
    "                num += 1\n",
    "        return round(pop / num, 6)\n",
    "    \n",
    "    def eval(self):\n",
    "        metric = {'Precision': self.precision(),\n",
    "                  'Recall': self.recall(),\n",
    "                  'Coverage': self.coverage(),\n",
    "                  'Popularity': self.popularity()}\n",
    "        print('Metric:', metric)\n",
    "        return metric"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二. 算法实现\n",
    "1. Random\n",
    "2. MostPopular\n",
    "3. UserCF\n",
    "4. UserIIF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 随机推荐\n",
    "def Random(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 可忽略\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation，推荐接口函数\n",
    "    '''\n",
    "    items = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            items[item] = 1\n",
    "    \n",
    "    def GetRecommendation(user):\n",
    "        # 随机推荐N个未见过的\n",
    "        user_items = set(train[user])\n",
    "        rec_items = {k: items[k] for k in items if k not in user_items}\n",
    "        rec_items = list(rec_items.items())\n",
    "        random.shuffle(rec_items)\n",
    "        return rec_items[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 热门推荐\n",
    "def MostPopular(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 可忽略\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    '''\n",
    "    items = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            if item not in items:\n",
    "                items[item] = 0\n",
    "            items[item] += 1\n",
    "        \n",
    "    def GetRecommendation(user):\n",
    "        # 随机推荐N个没见过的最热门的\n",
    "        user_items = set(train[user])\n",
    "        rec_items = {k: items[k] for k in items if k not in user_items}\n",
    "        rec_items = list(sorted(rec_items.items(), key=lambda x: x[1], reverse=True))\n",
    "        return rec_items[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 基于用户余弦相似度的推荐\n",
    "def UserCF(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 超参数，设置取TopK相似用户数目\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    '''\n",
    "    # 计算item->user的倒排索引\n",
    "    item_users = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            if item not in item_users:\n",
    "                item_users[item] = []\n",
    "            item_users[item].append(user)\n",
    "    \n",
    "    # 计算用户相似度矩阵\n",
    "    sim = {}\n",
    "    num = {}\n",
    "    for item in item_users:\n",
    "        users = item_users[item]\n",
    "        for i in range(len(users)):\n",
    "            u = users[i]\n",
    "            if u not in num:\n",
    "                num[u] = 0\n",
    "            num[u] += 1\n",
    "            if u not in sim:\n",
    "                sim[u] = {}\n",
    "            for j in range(len(users)):\n",
    "                if j == i: continue\n",
    "                v = users[j]\n",
    "                if v not in sim[u]:\n",
    "                    sim[u][v] = 0\n",
    "                sim[u][v] += 1\n",
    "    for u in sim:\n",
    "        for v in sim[u]:\n",
    "            sim[u][v] /= math.sqrt(num[u] * num[v])\n",
    "    \n",
    "    # 按照相似度排序\n",
    "    sorted_user_sim = {k: list(sorted(v.items(), \\\n",
    "                               key=lambda x: x[1], reverse=True)) \\\n",
    "                       for k, v in sim.items()}\n",
    "    \n",
    "    # 获取接口函数\n",
    "    def GetRecommendation(user):\n",
    "        items = {}\n",
    "        seen_items = set(train[user])\n",
    "        for u, _ in sorted_user_sim[user][:K]:\n",
    "            for item in train[u]:\n",
    "                # 要去掉用户见过的\n",
    "                if item not in seen_items:\n",
    "                    if item not in items:\n",
    "                        items[item] = 0\n",
    "                    items[item] += sim[user][u]\n",
    "        recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]\n",
    "        return recs\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. 基于改进的用户余弦相似度的推荐\n",
    "def UserIIF(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 超参数，设置取TopK相似用户数目\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    '''\n",
    "    # 计算item->user的倒排索引\n",
    "    item_users = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            if item not in item_users:\n",
    "                item_users[item] = []\n",
    "            item_users[item].append(user)\n",
    "    \n",
    "    # 计算用户相似度矩阵\n",
    "    sim = {}\n",
    "    num = {}\n",
    "    for item in item_users:\n",
    "        users = item_users[item]\n",
    "        for i in range(len(users)):\n",
    "            u = users[i]\n",
    "            if u not in num:\n",
    "                num[u] = 0\n",
    "            num[u] += 1\n",
    "            if u not in sim:\n",
    "                sim[u] = {}\n",
    "            for j in range(len(users)):\n",
    "                if j == i: continue\n",
    "                v = users[j]\n",
    "                if v not in sim[u]:\n",
    "                    sim[u][v] = 0\n",
    "                # 相比UserCF，主要是改进了这里\n",
    "                sim[u][v] += 1 / math.log(1 + len(users))\n",
    "    for u in sim:\n",
    "        for v in sim[u]:\n",
    "            sim[u][v] /= math.sqrt(num[u] * num[v])\n",
    "    \n",
    "    # 按照相似度排序\n",
    "    sorted_user_sim = {k: list(sorted(v.items(), \\\n",
    "                               key=lambda x: x[1], reverse=True)) \\\n",
    "                       for k, v in sim.items()}\n",
    "    \n",
    "    # 获取接口函数\n",
    "    def GetRecommendation(user):\n",
    "        items = {}\n",
    "        seen_items = set(train[user])\n",
    "        for u, _ in sorted_user_sim[user][:K]:\n",
    "            for item in train[u]:\n",
    "                # 要去掉用户见过的\n",
    "                if item not in seen_items:\n",
    "                    if item not in items:\n",
    "                        items[item] = 0\n",
    "                    items[item] += sim[user][u]\n",
    "        recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]\n",
    "        return recs\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三. 实验\n",
    "1. Random实验\n",
    "2. MostPopular实验\n",
    "3. UserCF实验，K=[5, 10, 20, 40, 80, 160]\n",
    "4. UserIIF实验, K=80\n",
    "\n",
    "M=8, N=10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment():\n",
    "    \n",
    "    def __init__(self, M, K, N, fp='../dataset/ml-1m/ratings.dat', rt='UserCF'):\n",
    "        '''\n",
    "        :params: M, 进行多少次实验\n",
    "        :params: K, TopK相似用户的个数\n",
    "        :params: N, TopN推荐物品的个数\n",
    "        :params: fp, 数据文件路径\n",
    "        :params: rt, 推荐算法类型\n",
    "        '''\n",
    "        self.M = M\n",
    "        self.K = K\n",
    "        self.N = N\n",
    "        self.fp = fp\n",
    "        self.rt = rt\n",
    "        self.alg = {'Random': Random, 'MostPopular': MostPopular, \\\n",
    "                    'UserCF': UserCF, 'UserIIF': UserIIF}\n",
    "    \n",
    "    # 定义单次实验\n",
    "    @timmer\n",
    "    def worker(self, train, test):\n",
    "        '''\n",
    "        :params: train, 训练数据集\n",
    "        :params: test, 测试数据集\n",
    "        :return: 各指标的值\n",
    "        '''\n",
    "        getRecommendation = self.alg[self.rt](train, self.K, self.N)\n",
    "        metric = Metric(train, test, getRecommendation)\n",
    "        return metric.eval()\n",
    "    \n",
    "    # 多次实验取平均\n",
    "    @timmer\n",
    "    def run(self):\n",
    "        metrics = {'Precision': 0, 'Recall': 0, \n",
    "                   'Coverage': 0, 'Popularity': 0}\n",
    "        dataset = Dataset(self.fp)\n",
    "        for ii in range(self.M):\n",
    "            train, test = dataset.splitData(self.M, ii)\n",
    "            print('Experiment {}:'.format(ii))\n",
    "            metric = self.worker(train, test)\n",
    "            metrics = {k: metrics[k]+metric[k] for k in metrics}\n",
    "        metrics = {k: metrics[k] / self.M for k in metrics}\n",
    "        print('Average Result (M={}, K={}, N={}): {}'.format(\\\n",
    "                              self.M, self.K, self.N, metrics))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.40358304977417\n",
      "Func splitData, run time: 2.1179611682891846\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.3952}\n",
      "Func worker, run time: 20.80728793144226\n",
      "Func splitData, run time: 2.039689064025879\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.03, 'Popularity': 4.384244}\n",
      "Func worker, run time: 22.058059692382812\n",
      "Func splitData, run time: 2.129431962966919\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 0.64, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.38938}\n",
      "Func worker, run time: 18.35742425918579\n",
      "Func splitData, run time: 2.0330629348754883\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 0.62, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.393025}\n",
      "Func worker, run time: 22.459643840789795\n",
      "Func splitData, run time: 2.0501880645751953\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 0.61, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.393217}\n",
      "Func worker, run time: 23.829069137573242\n",
      "Func splitData, run time: 1.952528953552246\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 0.57, 'Recall': 0.27, 'Coverage': 100.03, 'Popularity': 4.388441}\n",
      "Func worker, run time: 21.796540021896362\n",
      "Func splitData, run time: 2.1322124004364014\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.382586}\n",
      "Func worker, run time: 19.419902801513672\n",
      "Func splitData, run time: 1.9659440517425537\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.390586}\n",
      "Func worker, run time: 18.834516286849976\n",
      "Average Result (M=8, K=0, N=10): {'Precision': 0.61, 'Recall': 0.29125, 'Coverage': 100.0075, 'Popularity': 4.389584875000001}\n",
      "Func run, run time: 185.54872608184814\n"
     ]
    }
   ],
   "source": [
    "# 1. random实验\n",
    "M, N = 8, 10\n",
    "K = 0 # 为保持一致而设置，随便填一个值\n",
    "random_exp = Experiment(M, K, N, rt='Random')\n",
    "random_exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.403282880783081\n",
      "Func splitData, run time: 1.9211320877075195\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 12.85, 'Recall': 6.17, 'Coverage': 2.47, 'Popularity': 7.724273}\n",
      "Func worker, run time: 10.972801923751831\n",
      "Func splitData, run time: 1.9256069660186768\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 13.07, 'Recall': 6.26, 'Coverage': 2.28, 'Popularity': 7.721385}\n",
      "Func worker, run time: 10.841933012008667\n",
      "Func splitData, run time: 1.910295009613037\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 12.89, 'Recall': 6.16, 'Coverage': 2.44, 'Popularity': 7.722067}\n",
      "Func worker, run time: 10.727141857147217\n",
      "Func splitData, run time: 1.882903814315796\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 12.81, 'Recall': 6.15, 'Coverage': 2.49, 'Popularity': 7.723152}\n",
      "Func worker, run time: 10.670467138290405\n",
      "Func splitData, run time: 1.918154001235962\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 12.7, 'Recall': 6.11, 'Coverage': 2.47, 'Popularity': 7.724644}\n",
      "Func worker, run time: 10.960633993148804\n",
      "Func splitData, run time: 1.9205529689788818\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 12.9, 'Recall': 6.22, 'Coverage': 2.38, 'Popularity': 7.7234}\n",
      "Func worker, run time: 10.842862129211426\n",
      "Func splitData, run time: 1.9104499816894531\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 12.91, 'Recall': 6.21, 'Coverage': 2.47, 'Popularity': 7.721658}\n",
      "Func worker, run time: 10.716413974761963\n",
      "Func splitData, run time: 1.9528350830078125\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 12.53, 'Recall': 6.01, 'Coverage': 2.41, 'Popularity': 7.725531}\n",
      "Func worker, run time: 10.732755184173584\n",
      "Average Result (M=8, K=0, N=10): {'Precision': 12.832500000000001, 'Recall': 6.16125, 'Coverage': 2.42625, 'Popularity': 7.723263749999999}\n",
      "Func run, run time: 103.3697898387909\n"
     ]
    }
   ],
   "source": [
    "# 2. MostPopular实验\n",
    "M, N = 8, 10\n",
    "K = 0 # 为保持一致而设置，随便填一个值\n",
    "mp_exp = Experiment(M, K, N, rt='MostPopular')\n",
    "mp_exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.3605561256408691\n",
      "Func splitData, run time: 1.8727848529815674\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 16.9, 'Recall': 8.12, 'Coverage': 52.44, 'Popularity': 6.819093}\n",
      "Func worker, run time: 201.4078812599182\n",
      "Func splitData, run time: 2.1514930725097656\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 17.04, 'Recall': 8.16, 'Coverage': 52.06, 'Popularity': 6.815413}\n",
      "Func worker, run time: 183.0848479270935\n",
      "Func splitData, run time: 1.9143519401550293\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 16.91, 'Recall': 8.08, 'Coverage': 51.75, 'Popularity': 6.818886}\n",
      "Func worker, run time: 177.24900722503662\n",
      "Func splitData, run time: 1.8360939025878906\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 16.94, 'Recall': 8.14, 'Coverage': 52.14, 'Popularity': 6.817815}\n",
      "Func worker, run time: 182.475821018219\n",
      "Func splitData, run time: 1.805711030960083\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 17.06, 'Recall': 8.2, 'Coverage': 52.12, 'Popularity': 6.82111}\n",
      "Func worker, run time: 173.00265192985535\n",
      "Func splitData, run time: 1.801429033279419\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 16.75, 'Recall': 8.08, 'Coverage': 51.91, 'Popularity': 6.818678}\n",
      "Func worker, run time: 174.97946214675903\n",
      "Func splitData, run time: 1.80289626121521\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 16.68, 'Recall': 8.02, 'Coverage': 51.71, 'Popularity': 6.82425}\n",
      "Func worker, run time: 173.59705901145935\n",
      "Func splitData, run time: 1.803412914276123\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 16.86, 'Recall': 8.09, 'Coverage': 52.56, 'Popularity': 6.819087}\n",
      "Func worker, run time: 174.63527822494507\n",
      "Average Result (M=8, K=5, N=10): {'Precision': 16.8925, 'Recall': 8.11125, 'Coverage': 52.08624999999999, 'Popularity': 6.8192915}\n",
      "Func run, run time: 1456.9617431163788\n",
      "Func loadData, run time: 1.257431983947754\n",
      "Func splitData, run time: 1.8042638301849365\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 20.52, 'Recall': 9.86, 'Coverage': 41.95, 'Popularity': 6.982226}\n",
      "Func worker, run time: 173.35024309158325\n",
      "Func splitData, run time: 1.8343029022216797\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 20.46, 'Recall': 9.8, 'Coverage': 42.06, 'Popularity': 6.972529}\n",
      "Func worker, run time: 173.38346886634827\n",
      "Func splitData, run time: 1.808082103729248\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 20.61, 'Recall': 9.85, 'Coverage': 41.62, 'Popularity': 6.980192}\n",
      "Func worker, run time: 175.31061029434204\n",
      "Func splitData, run time: 1.8049170970916748\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 20.41, 'Recall': 9.81, 'Coverage': 41.47, 'Popularity': 6.97886}\n",
      "Func worker, run time: 174.2243037223816\n",
      "Func splitData, run time: 1.815324068069458\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 20.59, 'Recall': 9.9, 'Coverage': 41.5, 'Popularity': 6.980629}\n",
      "Func worker, run time: 174.46058702468872\n",
      "Func splitData, run time: 1.7919108867645264\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 20.33, 'Recall': 9.81, 'Coverage': 41.26, 'Popularity': 6.981318}\n",
      "Func worker, run time: 172.53949809074402\n",
      "Func splitData, run time: 1.8133158683776855\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 20.19, 'Recall': 9.71, 'Coverage': 41.49, 'Popularity': 6.976388}\n",
      "Func worker, run time: 169.70669603347778\n",
      "Func splitData, run time: 1.7420899868011475\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 20.58, 'Recall': 9.87, 'Coverage': 41.8, 'Popularity': 6.980981}\n",
      "Func worker, run time: 187.25051093101501\n",
      "Average Result (M=8, K=10, N=10): {'Precision': 20.46125, 'Recall': 9.826250000000002, 'Coverage': 41.64375, 'Popularity': 6.979140375}\n",
      "Func run, run time: 1416.0529160499573\n",
      "Func loadData, run time: 1.2509210109710693\n",
      "Func splitData, run time: 2.0944771766662598\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 23.11, 'Recall': 11.1, 'Coverage': 32.6, 'Popularity': 7.104519}\n",
      "Func worker, run time: 185.00779795646667\n",
      "Func splitData, run time: 1.8321330547332764\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.96, 'Recall': 10.99, 'Coverage': 33.0, 'Popularity': 7.094808}\n",
      "Func worker, run time: 182.49092984199524\n",
      "Func splitData, run time: 1.7799580097198486\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 23.2, 'Recall': 11.09, 'Coverage': 32.1, 'Popularity': 7.101386}\n",
      "Func worker, run time: 182.88875007629395\n",
      "Func splitData, run time: 1.7766752243041992\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 22.87, 'Recall': 10.99, 'Coverage': 32.77, 'Popularity': 7.101266}\n",
      "Func worker, run time: 181.71431589126587\n",
      "Func splitData, run time: 1.8331959247589111\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 23.0, 'Recall': 11.06, 'Coverage': 33.25, 'Popularity': 7.10377}\n",
      "Func worker, run time: 176.38355994224548\n",
      "Func splitData, run time: 1.7539498805999756\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 22.96, 'Recall': 11.07, 'Coverage': 32.48, 'Popularity': 7.10406}\n",
      "Func worker, run time: 178.63581705093384\n",
      "Func splitData, run time: 1.8071832656860352\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 22.83, 'Recall': 10.97, 'Coverage': 32.79, 'Popularity': 7.100858}\n",
      "Func worker, run time: 180.997900724411\n",
      "Func splitData, run time: 1.8272180557250977\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 23.0, 'Recall': 11.03, 'Coverage': 33.27, 'Popularity': 7.108237}\n",
      "Func worker, run time: 179.63274002075195\n",
      "Average Result (M=8, K=20, N=10): {'Precision': 22.99125, 'Recall': 11.037500000000001, 'Coverage': 32.7825, 'Popularity': 7.102363}\n",
      "Func run, run time: 1463.8790090084076\n",
      "Func loadData, run time: 1.2451589107513428\n",
      "Func splitData, run time: 1.7343308925628662\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 24.73, 'Recall': 11.88, 'Coverage': 25.8, 'Popularity': 7.204384}\n",
      "Func worker, run time: 190.66554594039917\n",
      "Func splitData, run time: 1.8477561473846436\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 24.66, 'Recall': 11.81, 'Coverage': 26.03, 'Popularity': 7.19405}\n",
      "Func worker, run time: 193.2389531135559\n",
      "Func splitData, run time: 1.8444321155548096\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 24.68, 'Recall': 11.8, 'Coverage': 25.66, 'Popularity': 7.20158}\n",
      "Func worker, run time: 188.7122507095337\n",
      "Func splitData, run time: 1.8413538932800293\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 24.46, 'Recall': 11.76, 'Coverage': 25.89, 'Popularity': 7.201308}\n",
      "Func worker, run time: 186.81220722198486\n",
      "Func splitData, run time: 1.8592839241027832\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 24.25, 'Recall': 11.66, 'Coverage': 25.76, 'Popularity': 7.204154}\n",
      "Func worker, run time: 197.69361400604248\n",
      "Func splitData, run time: 2.064145803451538\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 24.46, 'Recall': 11.8, 'Coverage': 26.04, 'Popularity': 7.205482}\n",
      "Func worker, run time: 192.9972779750824\n",
      "Func splitData, run time: 1.797558069229126\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 24.49, 'Recall': 11.77, 'Coverage': 26.12, 'Popularity': 7.199023}\n",
      "Func worker, run time: 185.58164811134338\n",
      "Func splitData, run time: 1.815227746963501\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 24.58, 'Recall': 11.79, 'Coverage': 25.79, 'Popularity': 7.207737}\n",
      "Func worker, run time: 188.1497700214386\n",
      "Average Result (M=8, K=40, N=10): {'Precision': 24.53875, 'Recall': 11.783749999999998, 'Coverage': 25.886249999999997, 'Popularity': 7.20221475}\n",
      "Func run, run time: 1540.0677690505981\n",
      "Func loadData, run time: 1.1918129920959473\n",
      "Func splitData, run time: 1.7471270561218262\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 25.23, 'Recall': 12.12, 'Coverage': 20.35, 'Popularity': 7.288647}\n",
      "Func worker, run time: 191.55905103683472\n",
      "Func splitData, run time: 1.7517518997192383\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 25.34, 'Recall': 12.13, 'Coverage': 20.2, 'Popularity': 7.280265}\n",
      "Func worker, run time: 190.3586311340332\n",
      "Func splitData, run time: 1.7286112308502197\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 25.22, 'Recall': 12.06, 'Coverage': 20.03, 'Popularity': 7.28649}\n",
      "Func worker, run time: 215.9616241455078\n",
      "Func splitData, run time: 1.7403991222381592\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 24.98, 'Recall': 12.01, 'Coverage': 20.29, 'Popularity': 7.288943}\n",
      "Func worker, run time: 192.13360381126404\n",
      "Func splitData, run time: 1.7304770946502686\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 24.78, 'Recall': 11.91, 'Coverage': 20.33, 'Popularity': 7.289041}\n",
      "Func worker, run time: 191.28253412246704\n",
      "Func splitData, run time: 1.7530970573425293\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 25.04, 'Recall': 12.08, 'Coverage': 20.4, 'Popularity': 7.290409}\n",
      "Func worker, run time: 209.25476503372192\n",
      "Func splitData, run time: 1.9062669277191162\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 25.17, 'Recall': 12.1, 'Coverage': 20.0, 'Popularity': 7.286132}\n",
      "Func worker, run time: 219.69454503059387\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func splitData, run time: 1.9378957748413086\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 25.11, 'Recall': 12.04, 'Coverage': 20.4, 'Popularity': 7.295018}\n",
      "Func worker, run time: 217.57287120819092\n",
      "Average Result (M=8, K=80, N=10): {'Precision': 25.10875, 'Recall': 12.056249999999999, 'Coverage': 20.25, 'Popularity': 7.288118125}\n",
      "Func run, run time: 1643.4831750392914\n",
      "Func loadData, run time: 1.2924230098724365\n",
      "Func splitData, run time: 1.8834781646728516\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 24.9, 'Recall': 11.96, 'Coverage': 15.34, 'Popularity': 7.369982}\n",
      "Func worker, run time: 248.86677980422974\n",
      "Func splitData, run time: 1.9202308654785156\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 25.07, 'Recall': 12.0, 'Coverage': 15.43, 'Popularity': 7.359478}\n",
      "Func worker, run time: 244.85498023033142\n",
      "Func splitData, run time: 1.9144361019134521\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 24.94, 'Recall': 11.92, 'Coverage': 15.51, 'Popularity': 7.365725}\n",
      "Func worker, run time: 233.78980898857117\n",
      "Func splitData, run time: 1.735440731048584\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 24.7, 'Recall': 11.87, 'Coverage': 15.57, 'Popularity': 7.367826}\n",
      "Func worker, run time: 218.3170599937439\n",
      "Func splitData, run time: 1.7129569053649902\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 24.54, 'Recall': 11.8, 'Coverage': 15.42, 'Popularity': 7.368641}\n",
      "Func worker, run time: 218.92201709747314\n",
      "Func splitData, run time: 1.7369437217712402\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 24.77, 'Recall': 11.95, 'Coverage': 15.52, 'Popularity': 7.370501}\n",
      "Func worker, run time: 217.8976969718933\n",
      "Func splitData, run time: 1.7374908924102783\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 24.9, 'Recall': 11.97, 'Coverage': 15.31, 'Popularity': 7.362657}\n",
      "Func worker, run time: 241.18968224525452\n",
      "Func splitData, run time: 1.9872171878814697\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 24.69, 'Recall': 11.84, 'Coverage': 15.04, 'Popularity': 7.375662}\n",
      "Func worker, run time: 251.5464129447937\n",
      "Average Result (M=8, K=160, N=10): {'Precision': 24.813750000000002, 'Recall': 11.91375, 'Coverage': 15.392499999999998, 'Popularity': 7.367559}\n",
      "Func run, run time: 1891.5019328594208\n"
     ]
    }
   ],
   "source": [
    "# 3. UserCF实验\n",
    "M, N = 8, 10\n",
    "for K in [5, 10, 20, 40, 80, 160]:\n",
    "    cf_exp = Experiment(M, K, N, rt='UserCF')\n",
    "    cf_exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.438131332397461\n",
      "Func splitData, run time: 2.045954942703247\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 25.36, 'Recall': 12.18, 'Coverage': 21.33, 'Popularity': 7.26129}\n",
      "Func worker, run time: 392.8560140132904\n",
      "Func splitData, run time: 1.8182199001312256\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 25.5, 'Recall': 12.21, 'Coverage': 21.39, 'Popularity': 7.248747}\n",
      "Func worker, run time: 372.19161105155945\n",
      "Func splitData, run time: 1.7963738441467285\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 25.39, 'Recall': 12.14, 'Coverage': 21.33, 'Popularity': 7.255987}\n",
      "Func worker, run time: 373.7826910018921\n",
      "Func splitData, run time: 2.0211751461029053\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 25.08, 'Recall': 12.05, 'Coverage': 21.4, 'Popularity': 7.259753}\n",
      "Func worker, run time: 371.92588996887207\n",
      "Func splitData, run time: 1.8175630569458008\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 24.92, 'Recall': 11.98, 'Coverage': 21.25, 'Popularity': 7.261206}\n",
      "Func worker, run time: 368.02053785324097\n",
      "Func splitData, run time: 1.8024423122406006\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 25.14, 'Recall': 12.12, 'Coverage': 21.4, 'Popularity': 7.26109}\n",
      "Func worker, run time: 373.1204378604889\n",
      "Func splitData, run time: 1.8195960521697998\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 25.19, 'Recall': 12.11, 'Coverage': 20.87, 'Popularity': 7.257091}\n",
      "Func worker, run time: 373.04570269584656\n",
      "Func splitData, run time: 1.8219950199127197\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 25.15, 'Recall': 12.06, 'Coverage': 21.57, 'Popularity': 7.265932}\n",
      "Func worker, run time: 365.2058880329132\n",
      "Average Result (M=8, K=80, N=10): {'Precision': 25.21625, 'Recall': 12.106250000000001, 'Coverage': 21.3175, 'Popularity': 7.2588870000000005}\n",
      "Func run, run time: 3006.6924328804016\n"
     ]
    }
   ],
   "source": [
    "# 4. UserIIF实验\n",
    "M, N = 8, 10\n",
    "K = 80 # 与书中保持一致\n",
    "iif_exp = Experiment(M, K, N, rt='UserIIF')\n",
    "iif_exp.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四. 实验结果\n",
    "\n",
    "1. Random实验\n",
    "\n",
    "    Running time: 185.54872608184814\n",
    "    \n",
    "    Average Result (M=8, K=0, N=10): \n",
    "    {'Precision': 0.61, 'Recall': 0.29, \n",
    "     'Coverage': 100.0, 'Popularity': 4.38958}\n",
    " \n",
    "2. MostPopular实验\n",
    "\n",
    "    Running time: 103.3697898387909\n",
    "    \n",
    "    Average Result (M=8, K=0, N=10): \n",
    "    {'Precision': 12.83, 'Recall': 6.16, \n",
    "    'Coverage': 2.43, 'Popularity': 7.72326}\n",
    "\n",
    "3. UserCF实验\n",
    "\n",
    "    Running time: 1456.9617431163788\n",
    "    \n",
    "    Average Result (M=8, K=5, N=10): \n",
    "    {'Precision': 16.89, 'Recall': 8.11,\n",
    "     'Coverage': 52.09, 'Popularity': 6.8192915}\n",
    "     \n",
    "    Running time: 1416.0529160499573\n",
    "    \n",
    "    Average Result (M=8, K=10, N=10): \n",
    "    {'Precision': 20.46, 'Recall': 9.83, \n",
    "     'Coverage': 41.64, 'Popularity': 6.979140375}\n",
    "     \n",
    "    Running time: 1463.8790090084076\n",
    "    \n",
    "    Average Result (M=8, K=20, N=10): \n",
    "    {'Precision': 22.99, 'Recall': 11.04, \n",
    "     'Coverage': 32.78, 'Popularity': 7.102363}\n",
    "     \n",
    "    Running time: 1540.0677690505981\n",
    "    \n",
    "    Average Result (M=8, K=40, N=10):\n",
    "    {'Precision': 24.54, 'Recall': 11.78, \n",
    "     'Coverage': 25.89, 'Popularity': 7.20221475}\n",
    "     \n",
    "    Running time: 1643.4831750392914\n",
    "    \n",
    "    Average Result (M=8, K=80, N=10): \n",
    "    {'Precision': 25.11, 'Recall': 12.06, \n",
    "     'Coverage': 20.25, 'Popularity': 7.288118125}\n",
    "     \n",
    "    Running time: 1891.5019328594208\n",
    "    \n",
    "    Average Result (M=8, K=160, N=10): \n",
    "    {'Precision': 24.81, 'Recall': 11.91, \n",
    "     'Coverage': 15.39, 'Popularity': 7.367559}\n",
    "     \n",
    "4. UserIIF实验\n",
    "    \n",
    "    Running time: 3006.6924328804016\n",
    "    \n",
    "    Average Result (M=8, K=80, N=10): \n",
    "    {'Precision': 25.22, 'Recall': 12.11, \n",
    "     'Coverage': 21.32, 'Popularity': 7.258887}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五. 总结\n",
    "1. 数据集分割的小技巧，用同样的seed\n",
    "2. 各个指标的实现，要注意\n",
    "3. 为每个用户推荐的时候是推荐他们**没有见过**的，因为测试集里面是这样的\n",
    "4. 倒排物品-用户索引，可进行时间优化\n",
    "5. 推荐的时候K和N各代表什么意思，要分开设置，先取TopK，然后取TopN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 附：运行日志（请双击看）\n",
    "\n",
    "1. Random实验\n",
    "Func loadData, run time: 1.40358304977417\n",
    "Func splitData, run time: 2.1179611682891846\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.3952}\n",
    "Func worker, run time: 20.80728793144226\n",
    "Func splitData, run time: 2.039689064025879\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.03, 'Popularity': 4.384244}\n",
    "Func worker, run time: 22.058059692382812\n",
    "Func splitData, run time: 2.129431962966919\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 0.64, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.38938}\n",
    "Func worker, run time: 18.35742425918579\n",
    "Func splitData, run time: 2.0330629348754883\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 0.62, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.393025}\n",
    "Func worker, run time: 22.459643840789795\n",
    "Func splitData, run time: 2.0501880645751953\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 0.61, 'Recall': 0.3, 'Coverage': 100.0, 'Popularity': 4.393217}\n",
    "Func worker, run time: 23.829069137573242\n",
    "Func splitData, run time: 1.952528953552246\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 0.57, 'Recall': 0.27, 'Coverage': 100.03, 'Popularity': 4.388441}\n",
    "Func worker, run time: 21.796540021896362\n",
    "Func splitData, run time: 2.1322124004364014\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.382586}\n",
    "Func worker, run time: 19.419902801513672\n",
    "Func splitData, run time: 1.9659440517425537\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 0.61, 'Recall': 0.29, 'Coverage': 100.0, 'Popularity': 4.390586}\n",
    "Func worker, run time: 18.834516286849976\n",
    "Average Result (M=8, K=0, N=10): {'Precision': 0.61, 'Recall': 0.29125, 'Coverage': 100.0075, 'Popularity': 4.389584875000001}\n",
    "Func run, run time: 185.54872608184814\n",
    "\n",
    "2. MostPopular实验\n",
    "Func loadData, run time: 1.403282880783081\n",
    "Func splitData, run time: 1.9211320877075195\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 12.85, 'Recall': 6.17, 'Coverage': 2.47, 'Popularity': 7.724273}\n",
    "Func worker, run time: 10.972801923751831\n",
    "Func splitData, run time: 1.9256069660186768\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 13.07, 'Recall': 6.26, 'Coverage': 2.28, 'Popularity': 7.721385}\n",
    "Func worker, run time: 10.841933012008667\n",
    "Func splitData, run time: 1.910295009613037\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 12.89, 'Recall': 6.16, 'Coverage': 2.44, 'Popularity': 7.722067}\n",
    "Func worker, run time: 10.727141857147217\n",
    "Func splitData, run time: 1.882903814315796\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 12.81, 'Recall': 6.15, 'Coverage': 2.49, 'Popularity': 7.723152}\n",
    "Func worker, run time: 10.670467138290405\n",
    "Func splitData, run time: 1.918154001235962\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 12.7, 'Recall': 6.11, 'Coverage': 2.47, 'Popularity': 7.724644}\n",
    "Func worker, run time: 10.960633993148804\n",
    "Func splitData, run time: 1.9205529689788818\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 12.9, 'Recall': 6.22, 'Coverage': 2.38, 'Popularity': 7.7234}\n",
    "Func worker, run time: 10.842862129211426\n",
    "Func splitData, run time: 1.9104499816894531\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 12.91, 'Recall': 6.21, 'Coverage': 2.47, 'Popularity': 7.721658}\n",
    "Func worker, run time: 10.716413974761963\n",
    "Func splitData, run time: 1.9528350830078125\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 12.53, 'Recall': 6.01, 'Coverage': 2.41, 'Popularity': 7.725531}\n",
    "Func worker, run time: 10.732755184173584\n",
    "Average Result (M=8, K=0, N=10): {'Precision': 12.832500000000001, 'Recall': 6.16125, 'Coverage': 2.42625, 'Popularity': 7.723263749999999}\n",
    "Func run, run time: 103.3697898387909\n",
    "\n",
    "3. UserCF实验\n",
    "Func loadData, run time: 1.3605561256408691\n",
    "Func splitData, run time: 1.8727848529815674\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 16.9, 'Recall': 8.12, 'Coverage': 52.44, 'Popularity': 6.819093}\n",
    "Func worker, run time: 201.4078812599182\n",
    "Func splitData, run time: 2.1514930725097656\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 17.04, 'Recall': 8.16, 'Coverage': 52.06, 'Popularity': 6.815413}\n",
    "Func worker, run time: 183.0848479270935\n",
    "Func splitData, run time: 1.9143519401550293\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 16.91, 'Recall': 8.08, 'Coverage': 51.75, 'Popularity': 6.818886}\n",
    "Func worker, run time: 177.24900722503662\n",
    "Func splitData, run time: 1.8360939025878906\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 16.94, 'Recall': 8.14, 'Coverage': 52.14, 'Popularity': 6.817815}\n",
    "Func worker, run time: 182.475821018219\n",
    "Func splitData, run time: 1.805711030960083\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 17.06, 'Recall': 8.2, 'Coverage': 52.12, 'Popularity': 6.82111}\n",
    "Func worker, run time: 173.00265192985535\n",
    "Func splitData, run time: 1.801429033279419\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 16.75, 'Recall': 8.08, 'Coverage': 51.91, 'Popularity': 6.818678}\n",
    "Func worker, run time: 174.97946214675903\n",
    "Func splitData, run time: 1.80289626121521\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 16.68, 'Recall': 8.02, 'Coverage': 51.71, 'Popularity': 6.82425}\n",
    "Func worker, run time: 173.59705901145935\n",
    "Func splitData, run time: 1.803412914276123\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 16.86, 'Recall': 8.09, 'Coverage': 52.56, 'Popularity': 6.819087}\n",
    "Func worker, run time: 174.63527822494507\n",
    "Average Result (M=8, K=5, N=10): {'Precision': 16.8925, 'Recall': 8.11125, 'Coverage': 52.08624999999999, 'Popularity': 6.8192915}\n",
    "Func run, run time: 1456.9617431163788\n",
    "Func loadData, run time: 1.257431983947754\n",
    "Func splitData, run time: 1.8042638301849365\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 20.52, 'Recall': 9.86, 'Coverage': 41.95, 'Popularity': 6.982226}\n",
    "Func worker, run time: 173.35024309158325\n",
    "Func splitData, run time: 1.8343029022216797\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 20.46, 'Recall': 9.8, 'Coverage': 42.06, 'Popularity': 6.972529}\n",
    "Func worker, run time: 173.38346886634827\n",
    "Func splitData, run time: 1.808082103729248\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 20.61, 'Recall': 9.85, 'Coverage': 41.62, 'Popularity': 6.980192}\n",
    "Func worker, run time: 175.31061029434204\n",
    "Func splitData, run time: 1.8049170970916748\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 20.41, 'Recall': 9.81, 'Coverage': 41.47, 'Popularity': 6.97886}\n",
    "Func worker, run time: 174.2243037223816\n",
    "Func splitData, run time: 1.815324068069458\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 20.59, 'Recall': 9.9, 'Coverage': 41.5, 'Popularity': 6.980629}\n",
    "Func worker, run time: 174.46058702468872\n",
    "Func splitData, run time: 1.7919108867645264\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 20.33, 'Recall': 9.81, 'Coverage': 41.26, 'Popularity': 6.981318}\n",
    "Func worker, run time: 172.53949809074402\n",
    "Func splitData, run time: 1.8133158683776855\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 20.19, 'Recall': 9.71, 'Coverage': 41.49, 'Popularity': 6.976388}\n",
    "Func worker, run time: 169.70669603347778\n",
    "Func splitData, run time: 1.7420899868011475\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 20.58, 'Recall': 9.87, 'Coverage': 41.8, 'Popularity': 6.980981}\n",
    "Func worker, run time: 187.25051093101501\n",
    "Average Result (M=8, K=10, N=10): {'Precision': 20.46125, 'Recall': 9.826250000000002, 'Coverage': 41.64375, 'Popularity': 6.979140375}\n",
    "Func run, run time: 1416.0529160499573\n",
    "Func loadData, run time: 1.2509210109710693\n",
    "Func splitData, run time: 2.0944771766662598\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 23.11, 'Recall': 11.1, 'Coverage': 32.6, 'Popularity': 7.104519}\n",
    "Func worker, run time: 185.00779795646667\n",
    "Func splitData, run time: 1.8321330547332764\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.96, 'Recall': 10.99, 'Coverage': 33.0, 'Popularity': 7.094808}\n",
    "Func worker, run time: 182.49092984199524\n",
    "Func splitData, run time: 1.7799580097198486\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 23.2, 'Recall': 11.09, 'Coverage': 32.1, 'Popularity': 7.101386}\n",
    "Func worker, run time: 182.88875007629395\n",
    "Func splitData, run time: 1.7766752243041992\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 22.87, 'Recall': 10.99, 'Coverage': 32.77, 'Popularity': 7.101266}\n",
    "Func worker, run time: 181.71431589126587\n",
    "Func splitData, run time: 1.8331959247589111\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 23.0, 'Recall': 11.06, 'Coverage': 33.25, 'Popularity': 7.10377}\n",
    "Func worker, run time: 176.38355994224548\n",
    "Func splitData, run time: 1.7539498805999756\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 22.96, 'Recall': 11.07, 'Coverage': 32.48, 'Popularity': 7.10406}\n",
    "Func worker, run time: 178.63581705093384\n",
    "Func splitData, run time: 1.8071832656860352\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 22.83, 'Recall': 10.97, 'Coverage': 32.79, 'Popularity': 7.100858}\n",
    "Func worker, run time: 180.997900724411\n",
    "Func splitData, run time: 1.8272180557250977\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 23.0, 'Recall': 11.03, 'Coverage': 33.27, 'Popularity': 7.108237}\n",
    "Func worker, run time: 179.63274002075195\n",
    "Average Result (M=8, K=20, N=10): {'Precision': 22.99125, 'Recall': 11.037500000000001, 'Coverage': 32.7825, 'Popularity': 7.102363}\n",
    "Func run, run time: 1463.8790090084076\n",
    "Func loadData, run time: 1.2451589107513428\n",
    "Func splitData, run time: 1.7343308925628662\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 24.73, 'Recall': 11.88, 'Coverage': 25.8, 'Popularity': 7.204384}\n",
    "Func worker, run time: 190.66554594039917\n",
    "Func splitData, run time: 1.8477561473846436\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 24.66, 'Recall': 11.81, 'Coverage': 26.03, 'Popularity': 7.19405}\n",
    "Func worker, run time: 193.2389531135559\n",
    "Func splitData, run time: 1.8444321155548096\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 24.68, 'Recall': 11.8, 'Coverage': 25.66, 'Popularity': 7.20158}\n",
    "Func worker, run time: 188.7122507095337\n",
    "Func splitData, run time: 1.8413538932800293\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 24.46, 'Recall': 11.76, 'Coverage': 25.89, 'Popularity': 7.201308}\n",
    "Func worker, run time: 186.81220722198486\n",
    "Func splitData, run time: 1.8592839241027832\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 24.25, 'Recall': 11.66, 'Coverage': 25.76, 'Popularity': 7.204154}\n",
    "Func worker, run time: 197.69361400604248\n",
    "Func splitData, run time: 2.064145803451538\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 24.46, 'Recall': 11.8, 'Coverage': 26.04, 'Popularity': 7.205482}\n",
    "Func worker, run time: 192.9972779750824\n",
    "Func splitData, run time: 1.797558069229126\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 24.49, 'Recall': 11.77, 'Coverage': 26.12, 'Popularity': 7.199023}\n",
    "Func worker, run time: 185.58164811134338\n",
    "Func splitData, run time: 1.815227746963501\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 24.58, 'Recall': 11.79, 'Coverage': 25.79, 'Popularity': 7.207737}\n",
    "Func worker, run time: 188.1497700214386\n",
    "Average Result (M=8, K=40, N=10): {'Precision': 24.53875, 'Recall': 11.783749999999998, 'Coverage': 25.886249999999997, 'Popularity': 7.20221475}\n",
    "Func run, run time: 1540.0677690505981\n",
    "Func loadData, run time: 1.1918129920959473\n",
    "Func splitData, run time: 1.7471270561218262\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 25.23, 'Recall': 12.12, 'Coverage': 20.35, 'Popularity': 7.288647}\n",
    "Func worker, run time: 191.55905103683472\n",
    "Func splitData, run time: 1.7517518997192383\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 25.34, 'Recall': 12.13, 'Coverage': 20.2, 'Popularity': 7.280265}\n",
    "Func worker, run time: 190.3586311340332\n",
    "Func splitData, run time: 1.7286112308502197\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 25.22, 'Recall': 12.06, 'Coverage': 20.03, 'Popularity': 7.28649}\n",
    "Func worker, run time: 215.9616241455078\n",
    "Func splitData, run time: 1.7403991222381592\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 24.98, 'Recall': 12.01, 'Coverage': 20.29, 'Popularity': 7.288943}\n",
    "Func worker, run time: 192.13360381126404\n",
    "Func splitData, run time: 1.7304770946502686\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 24.78, 'Recall': 11.91, 'Coverage': 20.33, 'Popularity': 7.289041}\n",
    "Func worker, run time: 191.28253412246704\n",
    "Func splitData, run time: 1.7530970573425293\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 25.04, 'Recall': 12.08, 'Coverage': 20.4, 'Popularity': 7.290409}\n",
    "Func worker, run time: 209.25476503372192\n",
    "Func splitData, run time: 1.9062669277191162\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 25.17, 'Recall': 12.1, 'Coverage': 20.0, 'Popularity': 7.286132}\n",
    "Func worker, run time: 219.69454503059387\n",
    "Func splitData, run time: 1.9378957748413086\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 25.11, 'Recall': 12.04, 'Coverage': 20.4, 'Popularity': 7.295018}\n",
    "Func worker, run time: 217.57287120819092\n",
    "Average Result (M=8, K=80, N=10): {'Precision': 25.10875, 'Recall': 12.056249999999999, 'Coverage': 20.25, 'Popularity': 7.288118125}\n",
    "Func run, run time: 1643.4831750392914\n",
    "Func loadData, run time: 1.2924230098724365\n",
    "Func splitData, run time: 1.8834781646728516\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 24.9, 'Recall': 11.96, 'Coverage': 15.34, 'Popularity': 7.369982}\n",
    "Func worker, run time: 248.86677980422974\n",
    "Func splitData, run time: 1.9202308654785156\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 25.07, 'Recall': 12.0, 'Coverage': 15.43, 'Popularity': 7.359478}\n",
    "Func worker, run time: 244.85498023033142\n",
    "Func splitData, run time: 1.9144361019134521\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 24.94, 'Recall': 11.92, 'Coverage': 15.51, 'Popularity': 7.365725}\n",
    "Func worker, run time: 233.78980898857117\n",
    "Func splitData, run time: 1.735440731048584\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 24.7, 'Recall': 11.87, 'Coverage': 15.57, 'Popularity': 7.367826}\n",
    "Func worker, run time: 218.3170599937439\n",
    "Func splitData, run time: 1.7129569053649902\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 24.54, 'Recall': 11.8, 'Coverage': 15.42, 'Popularity': 7.368641}\n",
    "Func worker, run time: 218.92201709747314\n",
    "Func splitData, run time: 1.7369437217712402\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 24.77, 'Recall': 11.95, 'Coverage': 15.52, 'Popularity': 7.370501}\n",
    "Func worker, run time: 217.8976969718933\n",
    "Func splitData, run time: 1.7374908924102783\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 24.9, 'Recall': 11.97, 'Coverage': 15.31, 'Popularity': 7.362657}\n",
    "Func worker, run time: 241.18968224525452\n",
    "Func splitData, run time: 1.9872171878814697\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 24.69, 'Recall': 11.84, 'Coverage': 15.04, 'Popularity': 7.375662}\n",
    "Func worker, run time: 251.5464129447937\n",
    "Average Result (M=8, K=160, N=10): {'Precision': 24.813750000000002, 'Recall': 11.91375, 'Coverage': 15.392499999999998, 'Popularity': 7.367559}\n",
    "Func run, run time: 1891.5019328594208\n",
    "\n",
    "4. UserIIF实验\n",
    "Func loadData, run time: 1.438131332397461\n",
    "Func splitData, run time: 2.045954942703247\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 25.36, 'Recall': 12.18, 'Coverage': 21.33, 'Popularity': 7.26129}\n",
    "Func worker, run time: 392.8560140132904\n",
    "Func splitData, run time: 1.8182199001312256\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 25.5, 'Recall': 12.21, 'Coverage': 21.39, 'Popularity': 7.248747}\n",
    "Func worker, run time: 372.19161105155945\n",
    "Func splitData, run time: 1.7963738441467285\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 25.39, 'Recall': 12.14, 'Coverage': 21.33, 'Popularity': 7.255987}\n",
    "Func worker, run time: 373.7826910018921\n",
    "Func splitData, run time: 2.0211751461029053\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 25.08, 'Recall': 12.05, 'Coverage': 21.4, 'Popularity': 7.259753}\n",
    "Func worker, run time: 371.92588996887207\n",
    "Func splitData, run time: 1.8175630569458008\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 24.92, 'Recall': 11.98, 'Coverage': 21.25, 'Popularity': 7.261206}\n",
    "Func worker, run time: 368.02053785324097\n",
    "Func splitData, run time: 1.8024423122406006\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 25.14, 'Recall': 12.12, 'Coverage': 21.4, 'Popularity': 7.26109}\n",
    "Func worker, run time: 373.1204378604889\n",
    "Func splitData, run time: 1.8195960521697998\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 25.19, 'Recall': 12.11, 'Coverage': 20.87, 'Popularity': 7.257091}\n",
    "Func worker, run time: 373.04570269584656\n",
    "Func splitData, run time: 1.8219950199127197\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 25.15, 'Recall': 12.06, 'Coverage': 21.57, 'Popularity': 7.265932}\n",
    "Func worker, run time: 365.2058880329132\n",
    "Average Result (M=8, K=80, N=10): {'Precision': 25.21625, 'Recall': 12.106250000000001, 'Coverage': 21.3175, 'Popularity': 7.2588870000000005}\n",
    "Func run, run time: 3006.6924328804016"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
